package com.trz.cqrs.core.configurer;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ApplicationEventMulticaster;
import org.springframework.context.event.SimpleApplicationEventMulticaster;
import org.springframework.retry.annotation.EnableRetry;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import javax.annotation.PostConstruct;
import java.util.concurrent.Executor;

import static java.util.concurrent.ThreadPoolExecutor.DiscardPolicy;

@Slf4j
@Configuration
@EnableAsync
@EnableScheduling
@EnableRetry
public class CqrsConfigurer {

    @PostConstruct
    public void init() {
        log.info("Current {} version {}", Constants.MODULE, getClass().getPackage().getImplementationVersion());
    }

    @Bean(Constants.EXECUTOR)
    public Executor threadPoolTaskExecutor() {
        return new ThreadPoolTaskExecutor() {{
            setCorePoolSize(Constants.Executor.CORE_POOL_SIZE);
            setMaxPoolSize(Constants.Executor.CORE_POOL_SIZE * 5);
            setKeepAliveSeconds(Constants.Executor.ALIVE_SECONDS);
            setQueueCapacity(Constants.Executor.QUEUE_CAPACITY);
            setWaitForTasksToCompleteOnShutdown(true);
            setRejectedExecutionHandler(new DiscardPolicy());
            setThreadNamePrefix(Constants.MODULE + "-");
        }};
    }

    @Bean
    public ApplicationEventMulticaster applicationEventMulticaster() {
        return new SimpleApplicationEventMulticaster() {{
            setTaskExecutor(threadPoolTaskExecutor());
        }};
    }

}
